package com.jinyi.wwdeng.autodialer.http

import android.content.Context
import android.util.Log
import com.jinyi.wwdeng.autodialer.utils.JsonFormat
import okhttp3.Call
import okhttp3.Callback
import okhttp3.FormBody
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import okio.IOException
import org.json.JSONObject
import java.io.File
import java.util.concurrent.TimeUnit
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

/**
 * 网络请求工具类
 */
class HttpUtil private constructor() {

    companion object {
        @Volatile
        private var instance: HttpUtil? = null

        fun getInstance(): HttpUtil {
            return instance ?: synchronized(this) {
                instance ?: HttpUtil().also { instance = it }
            }
        }
    }

    // OkHttpClient实例，使用单例避免重复创建
    private val okHttpClient: OkHttpClient by lazy {
        OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS) // 连接超时
            .readTimeout(30, TimeUnit.SECONDS)    // 读取超时
            .writeTimeout(30, TimeUnit.SECONDS)   // 写入超时
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY // 日志拦截器
            })
            .build()
    }

    // JSON媒体类型
    private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()

    /**
     * 发起GET请求
     * @param context 上下文（用于生命周期管理）
     * @param url 请求地址
     * @param params 请求参数（可选）
     * @param headers 请求头（可选）
     * @param callback 回调接口
     */
    fun get(context: Context, url: String, params: Map<String, String>? = null, headers: Map<String, String>? = null, callback: HttpCallback) {
        // 构建完整的URL（包含参数）
        val fullUrl = buildUrlWithParams(url, params)

        // 构建请求
        val requestBuilder = Request.Builder()
            .url(fullUrl)
            .get()

        // 添加请求头
        addHeaders(requestBuilder, headers)

        // 发起请求
        executeRequest(context, requestBuilder.build(), callback)
    }

    /**
     * 发起POST请求（JSON格式）
     * @param context 上下文
     * @param url 请求地址
     * @param jsonBody JSON请求体
     * @param headers 请求头（可选）
     * @param callback 回调接口
     */
    fun postJson(context: Context, url: String, jsonBody: String, headers: Map<String, String>? = null, callback: HttpCallback) {
        // 创建请求体
        val requestBody = jsonBody.toRequestBody(JSON_MEDIA_TYPE)

        // 构建请求
        val requestBuilder = Request.Builder()
            .url(url)
            .post(requestBody)

        // 添加请求头
        addHeaders(requestBuilder, headers)

        // 发起请求
        executeRequest(context, requestBuilder.build(), callback)
    }

    /**
     * 发起POST请求（表单格式）
     * @param context 上下文
     * @param url 请求地址
     * @param formParams 表单参数
     * @param headers 请求头（可选）
     * @param callback 回调接口
     */
    fun postForm(context: Context, url: String, formParams: Map<String, String>, headers: Map<String, String>? = null, callback: HttpCallback) {
        // 构建表单请求体
        val formBody = FormBody.Builder().apply {
            formParams.forEach { (key, value) ->
                add(key, value)
            }
        }.build()

        // 构建请求
        val requestBuilder = Request.Builder()
            .url(url)
            .post(formBody)

        // 添加请求头
        addHeaders(requestBuilder, headers)

        // 发起请求
        executeRequest(context, requestBuilder.build(), callback)
    }

    /**
     * 文件上传
     * @param context 上下文
     * @param url 上传地址
     * @param file 要上传的文件
     * @param fileParamName 文件参数名（服务器接收的文件字段名）
     * @param otherParams 其他参数（可选）
     * @param headers 请求头（可选）
     * @param callback 回调接口
     */
    fun uploadFile(context: Context, url: String,file: File, fileParamName: String, otherParams: Map<String, String>? = null, headers: Map<String, String>? = null, callback: HttpCallback) {
        // 创建Multipart请求体
        val requestBody = MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .apply {
                // 添加文件
                addFormDataPart(fileParamName, file.name, file.asRequestBody("multipart/form-data".toMediaTypeOrNull()))
                // 添加其他参数
                otherParams?.forEach { (key, value) ->
                    addFormDataPart(key, value)
                }
            }
            .build()

        // 构建请求
        val requestBuilder = Request.Builder()
            .url(url)
            .post(requestBody)

        // 添加请求头
        addHeaders(requestBuilder, headers)

        // 发起请求
        executeRequest(context, requestBuilder.build(), callback)
    }

    /**
     * post协程扩展函数
     */
    suspend fun postJsonSuspend(context: Context, url: String, jsonBody: String, headers: Map<String, String>? = null): JSONObject = suspendCoroutine { continuation ->
        postJson(context, url, jsonBody, headers, object : HttpCallback {
            override fun onSuccess(data: JSONObject) {
                continuation.resume(data)
            }
            override fun onFailure(error: String) {
                continuation.resumeWithException(Exception(error))
            }

            override fun onFinish() {
            }
        })
    }

    /**
     * 文件上传协程扩展函数
     */
    suspend fun uploadFileSuspend(context: Context, url: String, file: File, fileParamName: String, otherParams: Map<String, String>? = null, headers: Map<String, String>? = null): JSONObject = suspendCoroutine { continuation ->
        uploadFile(context, url, file, fileParamName, otherParams, headers, object : HttpCallback {
            override fun onSuccess(data: JSONObject) {
                continuation.resume(data)
            }
            override fun onFailure(error: String) {
                continuation.resumeWithException(Exception(error))
            }
            override fun onFinish() {
            }
        })
    }

    /**
     * 执行网络请求
     * @param context 上下文（用于生命周期管理）
     * @param request 请求对象
     * @param callback 回调接口
     */
    private fun executeRequest(context: Context, request: Request, callback: HttpCallback) {
        // 创建Call对象
        val call = okHttpClient.newCall(request)

        // 将Call对象与Context关联，便于取消请求
        val callManager = CallManager.getInstance()
        callManager.addCall(context, call)

        // 异步执行请求
        call.enqueue(object : Callback {
            override fun onResponse(call: Call, response: Response) {
                // 从管理器中移除已完成的请求
                callManager.removeCall(context, call)
                callback.onFinish()

                try {
                    // 检查请求是否被取消
                    if (call.isCanceled()) {
                        callback.onFailure("请求已取消")
                        return
                    }

                    // 检查响应是否成功
                    if (!response.isSuccessful) {
                        callback.onFailure("HTTP错误: ${response.code} - ${response.message}")
                        return
                    }

                    // 获取响应体
                    val responseBody = response.body.string()
                    if (responseBody.isEmpty()) {
                        callback.onFailure("响应体为空")
                        return
                    }
                    Thread {
                        Log.i("Http","data：" + JsonFormat.format(responseBody))
                    }.start()

                    // 统一解析为JSONObject
                    val jsonObject = JSONObject(responseBody)
                    callback.onSuccess(jsonObject)

                } catch (e: Exception) {
                    callback.onFailure("响应解析失败: ${e.message}")
                } finally {
                    response.close() // 确保响应被关闭
                }
            }

            override fun onFailure(call: Call, e: IOException) {
                // 从管理器中移除失败的请求
                callManager.removeCall(context, call)
                callback.onFinish()

                // 检查请求是否被取消
                if (call.isCanceled()) {
                    callback.onFailure("请求已取消")
                } else {
                    callback.onFailure("网络请求失败: ${e.message}")
                }
            }
        })
    }

    /**
     * 取消指定Context的所有请求
     * @param context 上下文
     */
    fun cancelRequests(context: Context) {
        CallManager.getInstance().cancelCalls(context)
    }

    /**
     * 构建带参数的URL
     */
    private fun buildUrlWithParams(url: String, params: Map<String, String>?): String {
        if (params.isNullOrEmpty()) return url

        val urlBuilder = url.toHttpUrlOrNull()?.newBuilder() ?: return url
        params.forEach { (key, value) ->
            urlBuilder.addQueryParameter(key, value)
        }
        return urlBuilder.build().toString()
    }

    /**
     * 添加请求头
     */
    private fun addHeaders(builder: Request.Builder, headers: Map<String, String>?) {
        headers?.forEach { (key, value) ->
            builder.addHeader(key, value)
        }
    }
}

/**
 * 请求回调接口
 */
interface HttpCallback {
    fun onSuccess(data: JSONObject)
    fun onFailure(error: String)
    fun onFinish()
}

/**
 * Call管理器 - 防止内存泄漏
 * 用于管理网络请求与Context的关联，便于统一取消请求
 */
class CallManager private constructor() {

    companion object {
        @Volatile
        private var instance: CallManager? = null

        fun getInstance(): CallManager {
            return instance ?: synchronized(this) {
                instance ?: CallManager().also { instance = it }
            }
        }
    }

    // 存储每个Context对应的Call列表
    private val callMap = mutableMapOf<Context, MutableList<Call>>()

    /**
     * 添加Call到管理器中
     */
    fun addCall(context: Context, call: Call) {
        synchronized(this) {
            if (!callMap.containsKey(context)) {
                callMap[context] = mutableListOf()
            }
            callMap[context]?.add(call)
        }
    }

    /**
     * 从管理器中移除Call
     */
    fun removeCall(context: Context, call: Call) {
        synchronized(this) {
            callMap[context]?.remove(call)
            // 如果该Context没有其他请求，移除Context条目
            if (callMap[context].isNullOrEmpty()) {
                callMap.remove(context)
            }
        }
    }

    /**
     * 取消指定Context的所有请求
     */
    fun cancelCalls(context: Context) {
        synchronized(this) {
            callMap[context]?.forEach { call ->
                if (!call.isCanceled()) {
                    call.cancel()
                }
            }
            callMap.remove(context)
        }
    }

    /**
     * 取消所有请求
     */
    fun cancelAll() {
        synchronized(this) {
            callMap.values.flatten().forEach { call ->
                if (!call.isCanceled()) {
                    call.cancel()
                }
            }
            callMap.clear()
        }
    }
}